import { calcDPR, useRightPosition } from '@amcax/base';
import { ModelEventType } from '@app-nextmesh/types';
import {
  drawColorMap,
  events,
  getColorMap,
  toScientificValue,
} from '@app-nextmesh/utils';
import { useEffect, useRef, useState } from 'react';

/**
 * 绘制尺度条
 * @param count 尺度条刻度数量
 * @param canvas 画布
 */
const drawRule = (count: number, canvas: HTMLCanvasElement) => {
  const width = canvas.width,
    height = canvas.height;
  const ctx = canvas.getContext('2d');
  const scaleWidth = width / 2; // 剩下的一半用来画colorbar
  const scaleHeight = 1 * calcDPR();
  for (let i = 0; i <= count; i++) {
    let y = (i * height) / count,
      w = 0,
      h = 0;
    if (i % 10 === 0) {
      w = scaleWidth;
      h = scaleHeight;
      if (i === count) {
        // 最后一个y坐标向上偏移一个scaleHeight
        y -= scaleHeight;
      }
    } else if (i % 5 === 0) {
      // 5 15
      w = (scaleWidth * 3) / 4;
      h = scaleHeight / 2;
    } else {
      w = scaleWidth / 2;
      h = scaleHeight / 4;
    }
    ctx.fillStyle = 'black';
    ctx.fillRect(width / 2, y, w, h);
  }
};

type IExtra = { min: number; max: number };

// 处理刻度尺精度现保留10位
const ColorScaleSpan = ({
  value,
  flex = 1,
}: {
  value: number;
  flex?: number;
}) => {
  return <span style={{ flex }}>{toScientificValue(value, 10)}</span>;
};

const ColorScale = ({ extra }: { extra?: IExtra }) => {
  if (!extra) {
    return <></>;
  }
  return (
    <div
      style={{
        display: 'flex',
        marginLeft: '5px',
        flexDirection: 'column',
        justifyContent: 'space-between',
        alignItems: 'start',
        height: '320px',
      }}>
      <ColorScaleSpan value={extra.min} />
      <ColorScaleSpan value={(extra.max + extra.min) / 2} />
      <ColorScaleSpan
        value={extra.max}
        flex={0}
      />
    </div>
  );
};

export default function ColorScaleBar() {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [colormap, setColormap] = useState<string>(null);
  const [extra, setExtra] = useState<IExtra>(null);
  const rightPosition = useRightPosition();

  useEffect(() => {
    events.on(ModelEventType.SetColormap, handleSetColormap);
    events.on(ModelEventType.SetExtra, handleSetExtra);
    events.on(ModelEventType.ResetColorbar, () => {
      setColormap(null);
      setExtra(null);
    });
    return () => {
      events.off(ModelEventType.SetColormap);
      events.off(ModelEventType.SetExtra);
      events.off(ModelEventType.ResetColorbar);
    };
  }, []);
  useEffect(() => {
    if (canvasRef.current) {
      const n = 20;
      drawRule(n, canvasRef.current);
      if (colormap) {
        const colorMap = getColorMap(colormap, n);
        drawColorMap(
          colorMap,
          colorMap.length,
          canvasRef.current,
          'vertically',
        );
      }
    }
  }, [canvasRef.current, colormap]);
  const handleSetColormap = (colormap: string) => {
    setColormap(colormap);
  };
  const handleSetExtra = (extra: IExtra) => {
    if (extra.min !== undefined && extra.max !== undefined) {
      setExtra(extra);
    }
  };
  if (colormap == null) {
    return <></>;
  }
  return (
    <div
      style={{
        position: 'absolute',
        marginBottom: '10px',
        top: '50%',
        transform: 'translateY(-50%)',
        right: `${rightPosition + 10}px`,
      }}>
      <div
        style={{
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}>
        <canvas
          ref={canvasRef}
          style={{ width: '30px', height: '300px' }}
        />
        <ColorScale extra={extra} />
      </div>
    </div>
  );
}
